<!doctype html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Bootstrap 情境色 + 霓虹贪吃蛇</title>
    <!-- Bootstrap 3 -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.4.1/dist/css/bootstrap.min.css">
    <style>
        /* ===== 仅留一套背景 ===== */
        body{background:#0f0f13;color:#e0e0e0;display:flex;align-items:center;justify-content:center;min-height:100vh;}
        .neon-glow{text-shadow:0 0 8px currentColor;}
        /* ===== 画布 ===== */
        #snakeCanvas{display:block;margin:20px auto;background:#111;border:2px solid #66afe9;border-radius:6px;}
        .score{text-align:center;font-size:1.5em;margin-top:10px;color:#66afe9;}
    </style>
</head>
<body>
<div class="container">
    <h2 class="page-header text-center text-info neon-glow">Bootstrap 情境颜色 + 霓虹贪吃蛇</h2>

    <!-- 1️⃣ 情境文本色 -->
    <div class="panel panel-default">
        <div class="panel-heading"><strong>情境文本颜色（text-*）</strong></div>
        <div class="panel-body">
            <p class="text-muted">text-muted：muted text</p>
            <p class="text-primary">text-primary：primary link</p>
            <p class="text-success">text-success：success tip</p>
            <p class="text-info">text-info：info note</p>
            <p class="text-warning">text-warning：warning hint</p>
            <p class="text-danger">text-danger：danger alert</p>
        </div>
    </div>

    <!-- 2️⃣ 情境背景色 -->
    <div class="panel panel-default">
        <div class="panel-heading"><strong>情境背景色（bg-*）</strong></div>
        <div class="panel-body">
            <p class="bg-primary text-center">bg-primary</p>
            <p class="bg-success text-center">bg-success</p>
            <p class="bg-info text-center">bg-info</p>
            <p class="bg-warning text-center">bg-warning</p>
            <p class="bg-danger text-center">bg-danger</p>
        </div>
    </div>

    <!-- 3️⃣ 关闭按钮 & 三角 -->
    <div class="panel panel-default">
        <div class="panel-heading"><strong>关闭按钮 & 三角符号</strong></div>
        <div class="panel-body text-center">
            <button type="button" class="close" aria-label="Close"><span aria-hidden="true">&times;</span></button>
            <hr><span class="caret"></span> 三角下拉
        </div>
    </div>

    <!-- 4️⃣ 霓虹贪吃蛇 -->
    <div class="panel panel-primary">
        <div class="panel-heading text-center"><strong>🐍 自动贪吃蛇（AI 自吃）</strong></div>
        <div class="panel-body">
            <canvas id="snakeCanvas" width="600" height="400"></canvas>
            <div class="score">得分：<span id="score">0</span></div>
        </div>
    </div>
</div>

<script>
    /* ========== 绝对最短路径自动吃食物 ========== */
    const CS = 20;
    const canvas = document.getElementById('snakeCanvas');
    const ctx   = canvas.getContext('2d');
    const W = canvas.width / CS, H = canvas.height / CS, SPEED = 100;

    let snake = Array.from({length:6},(_,i)=>({x:i,y:0}));
    let food  = randFood();
    let score = 0;
    let dir   = {x:1,y:0};          // 当前方向

    /* ------------ 工具 ------------ */
    function randFood(){
        let p;
        do p = {x:Math.floor(Math.random()*W),y:Math.floor(Math.random()*H)};
        while(snake.some(s=>s.x===p.x&&s.y===p.y));
        return p;
    }
    function drawCell(x,y,color){
        ctx.fillStyle=color;
        ctx.fillRect(x*CS+1,y*CS+1,CS-2,CS-2);
    }

    /* ------------ 核心：BFS 返回“吃到食物的下一步方向” ------------ */
    function nextDir(){
        const head = snake[0];
        const bodySet = new Set(snake.map(s=>`${s.x},${s.y}`)); // 身体墙
        const queue = [];
        const seen  = Array.from({length:H},()=>Array(W).fill(false));

        /* 四个方向：禁止 180° 回头 */
        const dirs = [{x:1,y:0},{x:-1,y:0},{x:0,y:1},{x:0,y:-1}]
            .filter(d=>!(d.x===-dir.x&&d.y===-dir.y)); // 不能反向

        for(const d of dirs){
            const nx = (head.x + d.x + W) % W, ny = (head.y + d.y + H) % H;
            if(bodySet.has(`${nx},${ny}`)) continue; // 撞身体
            if(nx===food.x && ny===food.y) return d; // 直接吃到
            queue.push({x:nx,y:ny,firstDir:d});
            seen[ny][nx] = true;
        }

        /* 标准 BFS */
        while(queue.length){
            const cur = queue.shift();
            for(const d of dirs){
                const nx = (cur.x + d.x + W) % W, ny = (cur.y + d.y + H) % H;
                if(seen[ny][nx] || bodySet.has(`${nx},${ny}`)) continue;
                if(nx===food.x && ny===food.y) return cur.firstDir; // 找到食物
                seen[ny][nx] = true;
                queue.push({x:nx,y:ny,firstDir:cur.firstDir});
            }
        }
        /* 无路可走时随便走（不会死） */
        return dirs[0] || {x:1,y:0};
    }

    /* ------------ 主循环 ------------ */
    function frame(){
        dir = nextDir();                       // 每帧重新找路
        const head = {x:(snake[0].x+dir.x+W)%W,y:(snake[0].y+dir.y+H)%H};
        snake.unshift(head);

        if(head.x===food.x&&head.y===food.y){
            score++;
            document.getElementById('score').textContent = score;
            food = randFood();
        }else snake.pop();

        /* 绘制 */
        ctx.clearRect(0,0,canvas.width,canvas.height);
        drawCell(food.x,food.y,'#ff6363');
        snake.forEach((s,i)=>drawCell(s.x,s.y,i===0?'#66afe9':'#4fc3f7'));
    }

    setInterval(frame, SPEED);
</script>


</body>
</html>
